DEFINITION MODULE  MathBase;

(*****************************************************************************)
(* In diesem Modul gibt es Grundfunktionen fuer die Behandlung von REAL- bzw.*)
(* LONGREAL-Zahlen, die bei der Programmierung mathematischer Funktionen     *)
(* verwendet werden koennen, da hierbei oft auf Teile der REAL-Repraesenta-  *)
(* tion zugegriffen wird.                                                    *)
(* Ausserdem gibt es noch einige Funktionen, die normalerweise in "MathLib0" *)
(* bzw. "LongMathLib0" angesiedelt sind, aber weil sie so grundlegend und    *)
(* keine 'hoeheren' Funktionen sind, habe ich sie hier reingepackt.          *)
(*                                                                           *)
(* Bis auf die Funktion "sarctan" kann das Modul als Ersatz fuer das Origi-  *)
(* nalmodul "MathCom" dienen ( "SplitReal" und "GetFraction" fuer die fehler-*)
(* haften "frexp" und "modf" und "MakeReal" fuer das wesentlich langsamere   *)
(* "ldexp" ).                                                                *)
(*___________________________________________________________________________*)
(*   26-Feb-90 , Holger Kleinschmidt                                         *)
(*****************************************************************************)

FROM  SYSTEM  IMPORT  (* PROC *) VAL;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)

CONST
      MAXint      =  32767.0;
      MINint      = -32768.0;
      MAXcard     =  65535.0;

      MAXREAL     = MAX( REAL );
      MINREAL     = VAL( REAL, 00800000H ); (* = 2^(-126) * 1.0 *)

      MAXlongint  = 2147483647.0D;
      MAXlongcard = 4294967295.0D;

      MAXLONGREAL = MAX( LONGREAL );


(***** ! DIE FOLGENDEN VARIABLEN NUR ALS KONSTANTE VERWENDEN ! *****)

VAR
      MINLONGREAL : LONGREAL;   (* wird mit der kleinsten darstellbaren
                                 * LONGREAL-Zahl initialisiert.
                                 *  = 2^(-1022) * 1.0D
                                 *)
      MINlongint  : LONGREAL;   (* wird mit der kleinsten LONGINT-Zahl
                                 * initialisiert.
                                 *)

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)

  PROCEDURE SplitReal     ((* EIN/ -- *)     value : REAL;
  (* = MathCom.frexp *)    (* -- /AUS *) VAR exp   : INTEGER ): REAL;

  PROCEDURE SplitLongReal ((* EIN/ -- *)     value : LONGREAL;
                           (* -- /AUS *) VAR exp   : INTEGER   ): LONGREAL;

 (*-------------------------------------------------------------------------
  | Spalten <value> in die Mantisse 'mant', die als Funktionswert geliefert |
  | wird, und den Exponenten <exp> auf; es gilt also:                       |
  |                                                                         |
  |          value = mant * 2^exp  , mit  1.0 <= |mant| < 2.0               |
  |                                                                         |
  | Ist <value> = 0.0, dann wird <exp> := 0 und mant := 0.0 .               |
   -------------------------------------------------------------------------*)


  PROCEDURE MakeReal     ((* EIN/ -- *) mant : REAL;
  (* = MathCom.ldexp *)   (* EIN/ -- *) exp  : INTEGER ): REAL;

  PROCEDURE MakeLongReal ((* EIN/ -- *) mant : LONGREAL;
                          (* EIN/ -- *) exp  : INTEGER   ): LONGREAL;

 (*-------------------------------------------------------------------------
  | <mant> und <exp> werden zu einer REAL-Zahl <value> zusammengesetzt, die |
  | als Funktionswert geliefert wird; es gilt:                              |
  |                                                                         |
  |          value = mant * 2^exp                                           |
  |                                                                         |
  | Da <mant> nicht notwendigerweise zwischen 1.0 und 2.0 liegen muss, son- |
  | dern eine beliebige REAL-Zahl sein kann, lassen sich die beiden Funkti- |
  | onen dazu verwenden, REAL-Zahlen sehr schnell mit Zweierpotenzen zu     |
  | multiplizieren ( exp > 0 ) oder auch zu dividieren ( exp < 0 )!         |
  | Die Multiplikation mit REAL-Zahlen ist z.B. ~100% schneller. Die Divi-  |
  | sion sogar ~160%.                                                       |
  |                                                                         |
  | Es gilt:       x := SplitReal( value, exp );                            |
  |                value = MakeReal( x, exp );                              |
  |                                                                         |
  | Ist <mant> = 0.0, wird auch 0.0 zurueckgeliefert.                       |
  | Kommt es zum Ueberlauf, wird MAX(REAL) zurueckgeliefert.                |
   -------------------------------------------------------------------------*)


  PROCEDURE GetFraction     ((* EIN/ -- *)     value : REAL;
  (* = MathCom.modf *)       (* -- /AUS *) VAR int   : INTEGER ): REAL;

  PROCEDURE GetLongFraction ((* EIN/ -- *)     value : LONGREAL;
                             (* -- /AUS *) VAR int   : INTEGER  ): LONGREAL;

 (*-------------------------------------------------------------------------
  | Spalten <value> in den ganzzahligen Anteil <int> samt Vorzeichen und den|
  | stets positiven gebrochenen Anteil <frac> auf, der als Funktionswert    |
  | geliefert wird.                                                         |
  |                                                                         |
  |               |value| = |int| + frac                                    |
  |                                                                         |
  | Es ist darauf zu achten, dass der Wertebereich fuer <int> nicht ueber-  |
  | schritten wird, sonst gibt es falsche Ergebnisse oder Laufzeitfehler.   |
   -------------------------------------------------------------------------*)


  PROCEDURE SIGN    ((* EIN/ -- *) zahl : REAL ): INTEGER;

  PROCEDURE SIGND   ((* EIN/ -- *) zahl : LONGREAL ): INTEGER;

  PROCEDURE INTSIGN ((* EIN/ -- *) zahl : LONGINT ): INTEGER;

 (*-------------------------------------------------------------------------
  | Signumsfunktion, INTSIGN ist auch fuer INTEGER-Zahlen geeignet.         |
  |                                                                         |
  |             / -1 , x < 0                                                |
  |   SIGN(x) = |  0 , x = 0                                                |
  |             \  1 , x > 0                                                |
   -------------------------------------------------------------------------*)


  PROCEDURE  real ((* EIN/ -- *) int : INTEGER ): REAL;

  PROCEDURE  Real ((* EIN/ -- *) lint : LONGINT ): LONGREAL;

 (*-------------------------------------------------------------------------
  | Wandeln die uebergebende ganze Zahl in eine reelle Zahl; es kann nicht  |
  | zu einem Ueberlauf kommen.                                              |
   -------------------------------------------------------------------------*)


  PROCEDURE  entier ((* EIN/ -- *) real : REAL ): INTEGER;

  PROCEDURE  Entier ((* EIN/ -- *) lreal : LONGREAL ): LONGINT;

 (*-------------------------------------------------------------------------
  | Wandeln die uebergebene reelle Zahl in die groesste ganze Zahl, die     |
  | kleiner oder gleich der reellen Zahl ist, somit besteht bei negativen   |
  | Zahlen zwischen TRUNC und "entier" ein Unterschied:                     |
  |                                                                         |
  |    TRUNC( -1.0 ) = entier( -1.0 ) = -1, aber                            |
  |    TRUNC( -1.1 ) = -1, entier( -1.1 ) = -2                              |
  |                                                                         |
  | Ueberschreitet die reelle Zahl den Wertebereich fuer die ganze Zahl,    |
  | wird die jeweils kleinste bzw. groesste darstellbare ganze Zahl zurueck-|
  | geliefert.                                                              |
  | MINint und MINlongint werden korrekt gewandelt.                         |
   -------------------------------------------------------------------------*)


  PROCEDURE  round ((* EIN/ -- *) real : REAL ): INTEGER;

  PROCEDURE  Round ((* EIN/ -- *) lreal : LONGREAL ): LONGINT;

 (*-------------------------------------------------------------------------
  | Liefern  TRUNC( x + 0.5 ) fuer positives  x, bzw.  TRUNC( x - 0.5 ) fuer|
  | negatives  x. Bei einem Ueberlauf wird die jeweils kleinste bzw.        |
  | groesste ganze Zahl zurueckgeliefert.                                   |
   -------------------------------------------------------------------------*)

END  MathBase.
